#ifndef NE_STL_INCLUDENE_STL_VALUE_DEF_H
#define NE_STL_INCLUDENE_STL_VALUE_DEF_H

#include "ne_stl_build.h"
#include "ne_stl_type_traits.h"

namespace nstd {

struct _container_npos : integral_constant<std::size_t, (std::size_t)(-1)> {};
using container_npos = _container_npos;

struct _container_increase_step : integral_constant<int32_t, 15> {};
using container_increase_step = _container_increase_step;

enum class stateful_bool : int32_t { kBegin = -1, kUnused = kBegin, kFalse = 0, kTrue = 1, kEnd };
template <stateful_bool _value>
using stateful_bool_constant = integral_constant<stateful_bool, _value>;
using stateful_bool_unused = stateful_bool_constant<stateful_bool::kUnused>;
using stateful_bool_true = stateful_bool_constant<stateful_bool::kTrue>;
using stateful_bool_false = stateful_bool_constant<stateful_bool::kFalse>;

#define NIM_STD_DBL_MAX (1.7976931348623156e+200)      // max value
#define NIM_STD_DBL_MIN (2.2250738585072014e-200)      // min positive value
#define NIM_STD_DBL_DEFAULT (1.7976931348623155e+200)  // def value
#define NIM_STD_DBL_EPSILON (2.2204460492503131e-16)   // epsilon

struct numeric_double_limits {
    inline static double epsilon_value() { return NIM_STD_DBL_EPSILON; }
    inline static double max_value() { return NIM_STD_DBL_MAX; }
    inline static double nim_value() { return NIM_STD_DBL_MIN; }
    inline static double default_value() { return NIM_STD_DBL_DEFAULT; }
    inline static bool is_equal(double valuea, double valueb) { return (fabs(valuea - valueb) <= epsilon_value()); }
    inline static bool is_default_value(double value) { return (is_equal(default_value(), value)); }
};
template <class first_type, class second_type>
struct pair {
    pair()
        : first()
        , second() {}

    template <class _first_type = first_type, class _second_type = second_type>
    pair(const _first_type& val1, const _second_type& val2)
        : first(val1)
        , second(val2) {}

    pair(const pair&) = default;

    template <class _self = pair>
    pair& operator=(const _self& right) {
        first = right.first;
        second = right.second;
        return *this;
    }

    void swap(pair& right) {
        if (this != std::addressof(right)) {
            swap(first, right.first);
            swap(second, right.second);
        }
    }
    first_type first;    // the first stored value
    second_type second;  // the second stored value
};
template <class first_type, class second_type>
pair<first_type, second_type> make_pair(const first_type& _first, const second_type& _second) {
    return pair<first_type, second_type>(_first, _second);
}
}  // namespace nstd

#endif  // !NE_STL_INCLUDENE_STL_VALUE_DEF_H
